<?php

namespace app\applet\library;

use app\common\model\UserApplet;
use max\Random;
use think\Config;
use think\Cookie;
use think\Request;
use think\Session;
use app\common\model\User as UserModel;

class Auth
{

    /**
     * @var object 对象实例
     */
    protected static $instance;
    protected $_error = '';
    protected $_return;
    protected $requestUri = '';
    protected $breadcrumb = [];
    public $logined = false; //登录状态
    public $id;

    public function __construct()
    {

    }

    public function __get($name)
    {
        return Session::get('user.' . $name);
    }

    /**
     * 初始化
     * @access public
     * @param array $options 参数
     * @return Auth
     */
    public static function instance($options = [])
    {
        if (is_null(self::$instance))
        {
            self::$instance = new static($options);
        }

        return self::$instance;
    }

    /**
     * 用户登录
     *
     * @param   string $username 用户名
     * @param   string $password 密码
     * @param   int $keeptime 有效时长
     * @return  boolean
     */
    public function login($username, $password)
    {
        $user = UserModel::get(['mobile' => $username]);
        if (!$user) {
            $this->setError('账号不存在');
            return false;
        }
        if ($user['status'] != 1) {
            $this->setError('当前账号不允许登录');
            return false;
        }
//        if (Config::get('maxerp.login_failure_retry') && $admin->loginfailure >= 10 && time() - $admin->updatetime < 86400) {
//            $this->setError('Please try again after 1 day');
//            return false;
//        }
        if ($user->password != md5(md5($password) . $user->salt)) {
//            $admin->loginfailure++;
//            $admin->save();
            $this->setError('账号或密码错误');
            return false;
        }
        $user->logintime = time();
        $clientip = $user->last_login_client_ip = get_client_ip();
        $clientiparr = explode('.',$clientip);
        $clientnum = array_sum($clientiparr);
        $token = $user->token = Random::uuid().'-'.$clientnum;
        $user->save();
        $login_cache = cache('user_login');
        $login_cache[$token] = $user;
        cache('user_login',$login_cache,60);
        $this->setReturn($token);
        $this->id = $user['id'];
        return true;
    }

    /**
     * 注销登录
     */
    public function logout()
    {
        $user = UserModel::get(intval($this->id));
        if (!$user) {
            return true;
        }
        $login_cache = cache('user_login');
        unset($login_cache[$user->token]);
        cache('user_login',$login_cache,60);
        $user->token = '';
        $user->save();
        return true;
    }

    /**
     * 自动登录
     * @return boolean
     */
    public function autologin()
    {
        $keeplogin = Cookie::get('keeplogin');
        if (!$keeplogin) {
            return false;
        }
        list($id, $keeptime, $expiretime, $key) = explode('|', $keeplogin);
        if ($id && $keeptime && $expiretime && $key && $expiretime > time()) {
            $admin = UserModel::get($id);
            if (!$admin || !$admin->token) {
                return false;
            }
            //token有变更
            if ($key != md5(md5($id) . md5($keeptime) . md5($expiretime) . $admin->token)) {
                return false;
            }
            Session::set("user", $admin->toArray());
            //刷新自动登录的时效
            $this->keeplogin($keeptime);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 刷新保持登录的Cookie
     *
     * @param   int $keeptime
     * @return  boolean
     */
    protected function keeplogin($keeptime = 0)
    {
        if ($keeptime) {
            $expiretime = time() + $keeptime;
            $key = md5(md5($this->id) . md5($keeptime) . md5($expiretime) . $this->token);
            $data = [$this->id, $keeptime, $expiretime, $key];
            Cookie::set('keeplogin', implode('|', $data), 86400 * 30);
            return true;
        }
        return false;
    }

    /**
     * 检测当前控制器和方法是否匹配传递的数组
     *
     * @param array $arr 需要验证权限的数组
     * @return bool
     */
    public function match($arr = [])
    {
        $request = Request::instance();
        $arr = is_array($arr) ? $arr : explode(',', $arr);
        if (!$arr) {
            return FALSE;
        }

        $arr = array_map('strtolower', $arr);
        // 是否存在
        if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) {
            return TRUE;
        }

        // 没找到匹配
        return FALSE;
    }

    /**
     * 检测是否登录
     *
     * @return boolean
     */
    public function isLogin($token)
    {
        if(empty($token))return false;
        $login_cache = cache('applet_login');
        if(!empty($login_cache[$token])){
           $user = $login_cache[$token];
        }else{
          //  $_m = new UserModel();
            $user = UserApplet::where(["token"=>$token])->field('id,mobile,logintime,token,last_login_client_ip,status')->find();
            if (!$user) {
                return false;
            }
            if ($user['status'] != 1) {
                return false;
            }
            if(time()-$user['logintime']>86400){
                return false;
            }
            $login_cache[$token] = $user;
            cache('applet_login',$login_cache,600);
        }
        $this->logined = true;
        halt($user);
        $this->id = $user['id'];
        return true;
    }

    /**
     * 获取当前请求的URI
     * @return string
     */
    public function getRequestUri()
    {
        return $this->requestUri;
    }

    /**
     * 设置当前请求的URI
     * @param string $uri
     */
    public function setRequestUri($uri)
    {
        $this->requestUri = $uri;
    }

    public function getUserInfo($uid = null)
    {
        $uid = is_null($uid) ? $this->id : $uid;

        return $uid != $this->id ? UserModel::get(intval($uid)) : Session::get('user');
    }

    /**
     * 设置错误信息
     *
     * @param string $error 错误信息
     * @return Auth
     */
    public function setError($error)
    {
        $this->_error = $error;
        return $this;
    }

    /**
     * 获取错误信息
     * @return string
     */
    public function getError()
    {
        return $this->_error ? __($this->_error) : '';
    }

    public function setReturn($return){
        $this->_return = $return;
        return $this;
    }

    public function getReturn(){
        return $this->_return;
    }
}
